Namespace ShapeLibrary
    '''
    ''' A ShapeContainer contains a collection of shapes.  This container uses
    ''' two designers:  a root designer that allows the container to be a top
    ''' level component where shapes can be visually added, and a normal designer
    ''' that is used when the shape container is added to another object like
    ''' a form.
    ''' 
    ''' ShapeContainer also defines a custom serializer.  This serializer is used
    ''' to generate code for an "adapter" class that can be used to fit a shape
    ''' to a Windows Forms paint event.
    ''' 
    ''' Finally, placing a ShapeContainer on another shape container is of
    ''' limited value, while placing it on other types of designers is 
    ''' what we intend.  So, we override the toolbox item filter that sits
    ''' on our base Shape class.
    '''
    <Designer(GetType(ShapeLibrary.Design.ShapeContainerRootDesigner), GetType(IRootDesigner)), _
    Designer(GetType(ShapeLibrary.Design.ShapeContainerDesigner)), _
    DesignerSerializer(GetType(ShapeLibrary.Design.ShapeContainerCodeDomSerializer), GetType(CodeDomSerializer)), _
    ToolboxItemFilter("ShapeLibrary.Shape", ToolboxItemFilterType.Prevent)> _
    Friend Class ShapeContainer
        Inherits Shape

        Private m_shapes As ShapeCollection

        '''
        '''  The collection of shapes within this container.
        '''
        <DesignerSerializationVisibility(DesignerSerializationVisibility.Content), _
        Browsable(False)> _
        Friend ReadOnly Property Shapes() As ShapeCollection
            Get
                If m_shapes Is Nothing Then
                    m_shapes = New ShapeCollection()
                End If
                Return m_shapes
            End Get
        End Property

        '''
        ''' Overrides Shape.Draw. This draws all the shapes in the container.
        '''
        Friend Overrides Sub Draw(ByVal g As Graphics)
            If Not (m_shapes Is Nothing) Then
                g.SmoothingMode = SmoothingMode.AntiAlias

                Dim s As Shape
                For Each s In m_shapes
                    s.Draw(g)
                Next s
            End If
        End Sub

        '''
        ''' This class implements a collection of shapes.
        '''
        Friend Class ShapeCollection
            Implements IList

            Private m_shapes As ArrayList = New ArrayList()

            Friend Sub New()
            End Sub

            Friend Function Add(ByVal value As Shape) As Integer
                Return m_shapes.Add(value)
            End Function

            Friend Sub AddRange(ByVal shapes As Shape())
                m_shapes.AddRange(shapes)
            End Sub

            Friend Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
                Return m_shapes.GetEnumerator()
            End Function

            Friend Sub Remove(ByVal value As Shape)
                m_shapes.Remove(value)
            End Sub

#Region "Implementation of IList"
            Sub RemoveAt(ByVal index As Integer) Implements IList.RemoveAt
                m_shapes.RemoveAt(index)
            End Sub

            Sub Insert(ByVal index As Integer, ByVal value As Object) Implements IList.Insert
                m_shapes.Insert(index, value)
            End Sub

            Sub Remove(ByVal value As Object) Implements IList.Remove
                m_shapes.Remove(value)
            End Sub

            Function Contains(ByVal value As Object) As Boolean Implements IList.Contains
                Return m_shapes.Contains(value)
            End Function

            Sub Clear() Implements IList.Clear
                m_shapes.Clear()
            End Sub

            Function IndexOf(ByVal value As Object) As Integer Implements IList.IndexOf
                Return m_shapes.IndexOf(value)
            End Function

            Function Add(ByVal value As Object) As Integer Implements IList.Add
                Return m_shapes.Add(value)
            End Function

            ReadOnly Property IsReadOnly() As Boolean Implements IList.IsReadOnly
                Get
                    Return False
                End Get
            End Property

            Property Item(ByVal index As Integer) As Object Implements IList.Item
                Get
                    Return m_shapes(index)
                End Get
                Set(ByVal Value As Object)
                    If Not (TypeOf Value Is Shape) Then
                        Throw New ArgumentException("value")
                    End If
                    m_shapes(index) = Value
                End Set
            End Property

            ReadOnly Property IsFixedSize() As Boolean Implements IList.IsFixedSize
                Get
                    Return False
                End Get
            End Property
#End Region

#Region "Implementation of ICollection"
            Sub CopyTo(ByVal array As Array, ByVal index As Integer) Implements ICollection.CopyTo
                m_shapes.CopyTo(array, index)
            End Sub

            ReadOnly Property IsSynchronized() As Boolean Implements ICollection.IsSynchronized
                Get
                    Return False
                End Get
            End Property

            ReadOnly Property Count() As Integer Implements ICollection.Count
                Get
                    Return m_shapes.Count
                End Get
            End Property

            ReadOnly Property SyncRoot() As Object Implements ICollection.SyncRoot
                Get
                    Return Me
                End Get
            End Property
#End Region
        End Class
    End Class
End Namespace
